-- card: 2857 from stack: in -- bmap block id: 0 -- flags: 4000 -- background id: 2611 -- name: Menu Card 1 ----- HyperTalk script ----- on openCard -- The variable containing the current menu item selection is reset -- to its initial level. The variable "blocs" contains the top and -- bottom locations for each menu item button, one pair to a line. -- The side coordinates are not needed because they are all the same -- and are given by the side coordinates of the menu field global b,blocs put 0 into b get rect of btn 1 put item 2 of it into blocs put item 4 of it into item 2 of blocs get rect of btn 2 put item 2 of it into line 2 of blocs put item 4 of it into item 2 of line 2 of blocs get rect of btn 3 put item 2 of it into line 3 of blocs put item 4 of it into item 2 of line 3 of blocs get rect of btn 4 put item 2 of it into line 4 of blocs put item 4 of it into item 2 of line 4 of blocs end openCard on mouseDown -- Sets the "ok" variable to true if the initial mouseDown occurs -- somewhere inside the simulated menubar, so the mouseStillDown -- handler will activate the menu if the cursor is subsequently -- dragged over the "apple" menu title. global ok put the mouseH into mH put the mouseV into mV if mH > 111 and mH < 393 and mV > 95 and mV < 114 then put true into ok else put false into ok end if end mouseDown on mouseStillDown -- Handles most of the actions of the menubar. Remember, once the -- mouse button is pressed this is the only message being sent by the -- HyperCard system, so checking the mouse position (i.e. is the -- cursor over a given button) cannot be gotten from mouseWithin or -- similar messages, but must be checked against the rectangle of -- the object being watched for. This handler had to be placed above -- the "apple" title button level so the mouseStillDown messages sent -- from the card level if the button is first depressed within the -- menubar but not over the actual "apple" title button would reach -- then same mouseStillDown handler and cause the menu to activate if -- the cursor is subsequently dragged over the "apple" title button. global b,blocs,ok -- First, if "ok" is true (the initial mouseDown occurred either over -- the "apple" menu title or somewhere else inside the menubar), -- allow the menu actions to take place. if ok then put the mouseV into mV -- Get the cursor location. put the mouseH into mH -- Check to see if the cursor has been dragged over the "apple" menu -- title. First, is the cursor above the bottom of the menubar? if mV < 113 then -- If so, is the cursor within the bounds of the "apple" menu? if mH < 121 or mH > 149 or mV < 97 then send mouseUp to btn 5 -- If it is over the "apple" menu, then else -- send the "apple" button a mouseDown send mouseDown to btn 5 -- (show the menu) otherwise send it a end if -- mouseUp (hide the menu). repeat with n = 1 to 4 -- Then un-hilite the menu item buttons. set hilite of btn n to false end repeat exit mouseStillDown -- And leave this message handler (no end if -- other actions will be necessary). -- If the cursor is below the menubar, is it somewhere over the -- menu field itself, and if so, over which button (which must be -- hilited)? if mV ≥ 113 and mV ≤ 178 and mH ≥ 121 and mH ≤ 231 then put b into oldB -- A place holder for the last button hilited. -- The following loop checks to find which menu item the cursor is -- over, and hilites the button over it so it appears to be -- selected. The variable "b" contains the number of the currently -- hilited button, and the search begins from the next higher ID -- button (the next one lower on the menu) so that when the menu -- is dragged _down_ (the most common direction to drag along a -- menu) the first button checked is the one immediately below the -- last button hilited, which improves the menu reaction just a -- bit when dragging the mouse _down_ the menu. The variable -- "blocs" contains the top and bottom coordinates for each menu -- item button, one pair to a line. repeat 4 times add 1 to b if b > 4 then put 1 into b -- Only four buttons are in the menu if mV ≥ item 1 of line b of blocs and mV < item 2 of line b of blocs then -- Once it is known which button the cursor is currently over -- that button is hilited, and the last menu item button -- hilited is un-hilited (if it is not the same as the new -- button, or it would blink on and off, and it is not 0, -- which is the reset number and not a button that can be -- unhilited). set hilite of btn b to true if oldB ≠ 0 and oldB ≠ b then set hilite of btn oldB to false exit mouseStillDown -- Leave this handler, no more actions end if -- necessary. end repeat else -- If the cursor is not over the menu while it is showing, then -- un-hilite all of the buttons and reset the currently selected -- button to 0. repeat with n = 1 to 4 set hilite of btn n to false end repeat put 0 into b end if end if end mouseStillDown on idle -- For a menu selection to take place the mouse button must be -- released over one of the hilited menu item buttons. Consequently -- there will be no mouseUp message sent to the object that was -- receiving the mouseStillDown messages (either the "apple" menu -- title button, or the card itself if the button is initially -- depressed within the menubar but not over the "apple" menu button). -- So the only way to have the menu react after the mouse button is -- released is to operate on the idle message which is then being -- sent. global b -- First, so the computer doesn't get tied up executing many -- HyperTalk commands while idle messages are being sent (which is -- all the time the mouse button is not depressed), the first thing -- this checks is whether the menu field itself is visible. If the -- field is not visible no menu items can have been selected, so -- the handler is quickly bypassed. if the visible of card field 1 then -- If variable "b" is not reset to 0 then a menu item has been -- selected, so the normal menu actions are executed. if b ≠ 0 then repeat 3 times -- The menu item selected is set hilite of btn b to false -- flashed three times. set hilite of btn b to true end repeat set hilite of btn b to false hide card field 1 -- The menu field is hidden, and the "apple" set hilite of btn 5 to false -- menu title button is un-hilited -- The number of the button over which the mouse button was -- released was set up so that it corresponded to the line number -- of the item selected in the menu field. To make the menu look -- better, two spaces were placed before each menu item, which -- must are removed before the doMenu command completes the menu -- action get line b of card field 1 delete char 1 to 2 of it doMenu it repeat with n = 1 to 4 -- Finally, when execution speed is no hide btn n -- longer a problem, the menu item buttons end repeat -- are hidden. else -- If variable "b" is 0 while the menu is showing, and the mouse -- button is then released, it means the cursor is not somewhere -- over the menu, so the menu and the item buttons are hidden -- and the "apple" menu button is un-hilited. hide card field 1 set hilite of btn 5 to false repeat with n = 1 to 4 hide btn n end repeat end if end if end idle -- part 6 (field) -- low flags: 80 -- high flags: 0004 -- rect: left=121 top=113 right=181 bottom=234 -- title width / last selected line: 0 -- icon id / first selected line: 0 / 0 -- text alignment: 0 -- font id: 0 -- text size: 12 -- style flags: 0 -- line height: 16 -- part name: Fake Menu Field -- part 1 (button) -- low flags: 80 -- high flags: 0000 -- rect: left=122 top=114 right=130 bottom=231 -- title width / last selected line: 0 -- icon id / first selected line: 0 / 0 -- text alignment: 1 -- font id: 0 -- text size: 12 -- style flags: 0 -- line height: 16 -- part name: New Button -- part 2 (button) -- low flags: 80 -- high flags: 0000 -- rect: left=122 top=130 right=146 bottom=231 -- title width / last selected line: 0 -- icon id / first selected line: 0 / 0 -- text alignment: 1 -- font id: 0 -- text size: 12 -- style flags: 0 -- line height: 16 -- part name: New Button -- part 3 (button) -- low flags: 80 -- high flags: 0000 -- rect: left=122 top=146 right=162 bottom=231 -- title width / last selected line: 0 -- icon id / first selected line: 0 / 0 -- text alignment: 1 -- font id: 0 -- text size: 12 -- style flags: 0 -- line height: 16 -- part name: New Button -- part 4 (button) -- low flags: 80 -- high flags: 0000 -- rect: left=122 top=162 right=178 bottom=231 -- title width / last selected line: 0 -- icon id / first selected line: 0 / 0 -- text alignment: 1 -- font id: 0 -- text size: 12 -- style flags: 0 -- line height: 16 -- part name: -- part 5 (button) -- low flags: 00 -- high flags: 8000 -- rect: left=121 top=97 right=113 bottom=149 -- title width / last selected line: 0 -- icon id / first selected line: 0 / 0 -- text alignment: 1 -- font id: 0 -- text size: 12 -- style flags: 0 -- line height: 16 -- part name:  ----- HyperTalk script ----- on mouseUp -- The menu field is hidden, the "apple" global b -- menu title is un-hilited, the buttons hide card field 1 -- that sit over the menu items are hidden, set hilite of me to false -- and the variable containing the current repeat with n = 1 to 4 -- menu item selection (b) is reset. hide btn n end repeat put 0 into b end mouseUp on mouseDown -- The "apple" menu title is hilited, the global b,ok -- menu field is shown, the buttons that sit set hilite of me to true -- over the menu items are shown, the show card field 1 -- variable containing the current menu item repeat with n = 1 to 4 -- selection (b) is reset, and the variable show button id n -- (ok) that tells the mouseStillDown handler end repeat -- whether or not to allow a drag over the put 0 into b -- menu title to activate the menu is set. put true into ok end mouseDown -- The mouseStillDown handler is placed at the card level, because there -- is another mouseDown handler at the card level (that sets the "ok" -- variable to true if the initial mouseDown is inside the menubar but -- not over the "apple" menu title) which uses the same mouseStillDown -- handler. The mouseStillDown handler does most of the tasks that make -- the menubar function. -- part 8 (button) -- low flags: 00 -- high flags: 2000 -- rect: left=362 top=215 right=235 bottom=383 -- title width / last selected line: 0 -- icon id / first selected line: 19678 / 19678 -- text alignment: 1 -- font id: 0 -- text size: 12 -- style flags: 0 -- line height: 16 -- part name: About This Stack ----- HyperTalk script ----- on mouseUp set scroll of card field 2 to 0 hide btn 7 hide btn id 14 hide btn id 18 hide btn id 20 show card field 2 end mouseUp -- part 9 (field) -- low flags: 81 -- high flags: 0007 -- rect: left=12 top=56 right=299 bottom=497 -- title width / last selected line: 0 -- icon id / first selected line: 0 / 0 -- text alignment: 0 -- font id: 4 -- text size: 9 -- style flags: 0 -- line height: 12 -- part name: About field ----- HyperTalk script ----- on mouseUp hide card field 2 show btn 7 show btn id 14 show btn id 18 show btn id 20 end mouseUp -- part 10 (field) -- low flags: 80 -- high flags: 0007 -- rect: left=21 top=33 right=285 bottom=491 -- title width / last selected line: 0 -- icon id / first selected line: 0 / 0 -- text alignment: 0 -- font id: 4 -- text size: 9 -- style flags: 0 -- line height: 12 -- part name: Temp Script Holder -- part 11 (button) -- low flags: 00 -- high flags: A003 -- rect: left=185 top=272 right=294 bottom=316 -- title width / last selected line: 0 -- icon id / first selected line: 0 / 0 -- text alignment: 1 -- font id: 0 -- text size: 12 -- style flags: 0 -- line height: 16 -- part name: Show Menu Parts ----- HyperTalk script ----- on mouseUp if card field 3 is empty then put the script of this card into card field 3 put the script of btn id 5 into card field 4 set script of this card to empty set script of btn id 5 to empty show card field 1 repeat with n = 1 to 4 show btn n end repeat set name of me to "Hide Menu Parts" show card field 5 set userLevel to 5 choose button tool show tool window set loc of tool window to 18,111 else set the script of this card to card field 3 set the script of btn id 5 to card field 4 put empty into card field 3 put empty into card field 4 hide card field 5 repeat with n = 1 to 4 hide btn n end repeat hide card field 1 set name of me to "Show Menu Parts" if the hilite of btn "do browsing" then set userLevel to 1 end if end mouseUp -- part 12 (field) -- low flags: 80 -- high flags: 0007 -- rect: left=30 top=60 right=159 bottom=474 -- title width / last selected line: 0 -- icon id / first selected line: 0 / 0 -- text alignment: 0 -- font id: 4 -- text size: 9 -- style flags: 0 -- line height: 12 -- part name: Temp Script Holder -- part 13 (field) -- low flags: 81 -- high flags: 2002 -- rect: left=151 top=33 right=75 bottom=345 -- title width / last selected line: 0 -- icon id / first selected line: 0 / 0 -- text alignment: 1 -- font id: 0 -- text size: 12 -- style flags: 0 -- line height: 16 -- part name: Warning (danger, Will Robinson!) -- part 14 (button) -- low flags: 00 -- high flags: A003 -- rect: left=160 top=305 right=327 bottom=346 -- title width / last selected line: 0 -- icon id / first selected line: 0 / 0 -- text alignment: 1 -- font id: 0 -- text size: 12 -- style flags: 0 -- line height: 16 -- part name: Remove Script Comments ----- HyperTalk script ----- on mouseUp hide msg if the optionKey is down then if the short name of me is "remove script comments" then answer "This will reset scripts for comment removal." with "OK" or "Cancel" if it is not "cancel" then put empty into card field id 15 put empty into card field id 16 put empty into card field id 17 end if end if else put false into done if the short name of me is "remove script comments" then if card field id 15 is empty and card field id 16 is empty and card field id 17 is empty then answer "Comments may be restored later" with "Cancel" or "OK" if it is "Cancel" then exit mouseUp else set loc of msg to 17,140 set cursor to 4 repeat with x = 1 to 3 if x = 1 then put the script of this stack into scriptHolder put "the stack script" into theName end if if x = 2 then put the script of this card into scriptHolder put "the card script" into theName end if if x = 3 then put the script of btn id 5 into scriptHolder put "the" && quote & "apple" & quote && "button script" into theName end if put the number of lines in scriptHolder into theLines put 1 into n repeat until n = theLines put "Removing comments from line" && n && "out of" && theLines && "of" && theName put the number of chars in line n of scriptHolder into theChars put offset("-",line n of scriptHolder) into start if start ≠ 0 then put false into exiit repeat until exiit if char start-1 of line n of scriptHolder is " " then subtract one from start else put true into exiit end if end repeat delete char start to theChars of line n of scriptHolder repeat until exiit if first char of line n of scriptHolder is " " then delete first char of line n of scriptHolder else put true into exiit end if end repeat end if if line n of scriptHolder is empty then delete line n of scriptHolder else add 1 to n end if put the number of lines in scriptHolder into theLines end repeat if x = 1 then put scriptHolder into stackHolder if x = 2 then put scriptHolder into cardHolder if x = 3 then put scriptHolder into btnHolder end repeat put " Finished!" wait 1 seconds hide msg put true into done end if end if set the name of me to "Restore Script Comments" hide btn id 19 else set the name of me to "Remove Script Comments" show btn id 19 end if set cursor to 4 if not done then put card field id 15 into stackHolder put card field id 16 into cardHolder put card field id 17 into btnHolder end if put the script of this stack into card field id 15 put the script of this card into card field id 16 put the script of btn id 5 into card field id 17 set the script of this stack to stackHolder set the script of this card to cardHolder set the script of btn id 5 to btnHolder end if end mouseUp -- part 15 (field) -- low flags: 80 -- high flags: 0002 -- rect: left=152 top=46 right=58 bottom=164 -- title width / last selected line: 0 -- icon id / first selected line: 0 / 0 -- text alignment: 0 -- font id: 4 -- text size: 9 -- style flags: 0 -- line height: 12 -- part name: Stack Script -- part 16 (field) -- low flags: 80 -- high flags: 0002 -- rect: left=247 top=46 right=58 bottom=259 -- title width / last selected line: 0 -- icon id / first selected line: 0 / 0 -- text alignment: 0 -- font id: 4 -- text size: 9 -- style flags: 0 -- line height: 12 -- part name: Card Script -- part 17 (field) -- low flags: 80 -- high flags: 0002 -- rect: left=346 top=45 right=57 bottom=358 -- title width / last selected line: 0 -- icon id / first selected line: 0 / 0 -- text alignment: 0 -- font id: 4 -- text size: 9 -- style flags: 0 -- line height: 12 -- part name: Button Script -- part 18 (button) -- low flags: 00 -- high flags: C006 -- rect: left=397 top=277 right=299 bottom=502 -- title width / last selected line: 0 -- icon id / first selected line: 0 / 0 -- text alignment: 1 -- font id: 0 -- text size: 12 -- style flags: 0 -- line height: 16 -- part name: Do Scripting ----- HyperTalk script ----- on mouseUp set hilite of me to true set hilite of btn "do browsing" to false set userLevel to 5 end mouseUp -- part 20 (button) -- low flags: 00 -- high flags: 8006 -- rect: left=397 top=308 right=330 bottom=502 -- title width / last selected line: 0 -- icon id / first selected line: 0 / 0 -- text alignment: 1 -- font id: 0 -- text size: 12 -- style flags: 0 -- line height: 16 -- part name: Do Browsing ----- HyperTalk script ----- on mouseUp set hilite of me to true set hilite of btn "do scripting" to false set userLevel to 1 end mouseUp -- part contents for card part 6 ----- text ----- Alarm Clock Control Panel Key Caps Scrapbook -- part contents for card part 9 ----- text ----- ********************************************* * * * Menu Emulation * * by William G. Anderson, Jr. * * April 1988 * * * * CIS id 76254,356 * * * ********************************************* This stack is an exercise to simulate the actions of the menubar using nothing but HyperTalk. Granted the objects involved do not react as quickly as those of a real menubar, but if you pass over the menu items slowly enough they will do a passable imitation of a real menubar. This was written on a Mac+ with a Radius accelerator board, so on non-accelerated Macs it may be very slow (I have no way to know). A hard disk also speeds things up considerably. Special notes: 1. The scripts of this stack, which are located at the stack level, the card level, and in the "apple" button (which is the title of the simulated menubar), are all heavily commented for your convenience. I can't be sure, but this does seem to slow the action of the simulated menu slighty. It also obscures the structure of the scripts. Therefore, I have included a button to strip the comments from the scripts of this stack. The actual removal of comments only happens the first time the button is used, at which time both the commented and uncommented versions of the scripts are stored. Future use of the button merely places the stored version into the script, and the script version goes into storage. So you can quickly toggle between the two versions as needed. (If you wish to remove the comments again and watch the numbers sail by, hold down the option key while clicking on the "remove script comments" button. This will reset the scripts and fields so the next mouse up will remove the comments again, while considerably shrinking the size of this stack.) 2. The locations and numbers of the buttons and field used by the scripts are fixed whithin the scripts themselves. If you move, remove, or change the size of any of these objects the simulation will fail unless you change the scripts to accomodate the changes you make. 3. There is an idle message handler that removes the menu field and its buttons from the screen when they are visible. Also, the "apple" menu button itself will similarly hide the menu field and buttons. To make it possible for you to examine the menu and its buttons, the "Show Menu Parts" button temporarily stores the "apple" menu button script and card level scripts in hidden fields, sets the user level to "scripting," shows the tool window and chooses the button tool (to show the menu item buttons over the menu field). When you are finished examining the menu field and its buttons, clicking on the "Hide Menu Parts" button will restore the card and button scripts, resetting the menu emulation. Actions performed by the simulated menu: (Any mention below of terms such as "menu" or "menubar" refer to the simulated menubar in the center of the screen, not the real one. Also, all references to "dragging" the mouse mean a continuous mouse down from the time the mouse was first clicked over some area that would normally actuate the menu.) 1. A mouseDown on the "apple" menu title causes the menu title to hilite, and the menu to show. 2. Dragging the mouse over the items of the menu causes them to hilite when the mouse is over them, and un-hilite when the mouse is no longer over them. 3. Dragging the mouse completely off the menu itself (to either side or the bottom) causes all menu items to be un-selected. 4. Dragging the mouse back over the menu while still below the menubar causes the menu item first dragged over to hilite. 5. Releasing the mouse button while over a hilited menu item causes the menu item to blink on and off three times, the menu disappears from the screen, the menu title un-hilites, and the selected action occurs. 6. Releasing the mouse button while the menu is showing but no menu items are hilited (i.e. the mouse is below the menubar but is to one side of or below the menu) causes the menu to disappear and the menu title to un- hilite. 7. If the cursor is no longer over the menu title when the cursor is dragged above the bottom of the menubar the menu disappears and the menu title will un-hilite. 8. After the occurance of item 7 above, dragging the mouse over the menu title causes the menu title to hilite and the menu will reappear. 9. If the mouseDown initially occurs somewhere inside the menubar, but not over the menu title itself, dragging the cursor over the menu title will cause the menu title to hilite and the menu will appear. 10. Dragging the cursor _down_ the menu will cause the menu items passed over to hilite and un-hilite faster than when dragging _up_ the menu. It was simple to optimize the script for one direction or the other, and since menus are initially scanned down I selected that direction to have the better reaction time. Note: While writing this I found that having any graphics in the card layer substantially slowed the speed at which the HyperTalk scripts used in this stack ran. Perhaps it is not a good idea to put graphics in the card layer at all, if it can be avoided. -- part contents for card part 13 ----- text ----- Click on button "Hide Menu Parts" to re-enable menu